{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Adadelta from scratch\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2017-10-22T11:50:58.551666Z",
     "start_time": "2017-10-22T11:50:57.361870Z"
    }
   },
   "outputs": [],
   "source": [
    "from mxnet import ndarray as nd\n",
    "\n",
    "# Adadalta.\n",
    "def adadelta(params, sqrs, deltas, rho, batch_size):\n",
    "    eps_stable = 1e-5\n",
    "    for param, sqr, delta in zip(params, sqrs, deltas):\n",
    "        g = param.grad / batch_size\n",
    "        sqr[:] = rho * sqr + (1. - rho) * nd.square(g)\n",
    "        cur_delta = nd.sqrt(delta + eps_stable) / nd.sqrt(sqr + eps_stable) * g\n",
    "        delta[:] = rho * delta + (1. - rho) * cur_delta * cur_delta\n",
    "        # update weight\n",
    "        param[:] -= cur_delta   \n",
    "\n",
    "import mxnet as mx\n",
    "from mxnet import autograd\n",
    "\n",
    "from mxnet import gluon\n",
    "import random\n",
    "\n",
    "mx.random.seed(1)\n",
    "random.seed(1)\n",
    "\n",
    "# Generate data.\n",
    "num_inputs = 2\n",
    "num_examples = 1000\n",
    "true_w = [2, -3.4]\n",
    "true_b = 4.2\n",
    "X = nd.random_normal(scale=1, shape=(num_examples, num_inputs))\n",
    "y = true_w[0] * X[:, 0] + true_w[1] * X[:, 1] + true_b\n",
    "y += .01 * nd.random_normal(scale=1, shape=y.shape)\n",
    "dataset = gluon.data.ArrayDataset(X, y)\n",
    "\n",
    "\n",
    "# Construct data iterator.\n",
    "def data_iter(batch_size):\n",
    "    idx = list(range(num_examples))\n",
    "    random.shuffle(idx)\n",
    "    for batch_i, i in enumerate(range(0, num_examples, batch_size)):\n",
    "        j = nd.array(idx[i: min(i + batch_size, num_examples)])\n",
    "        yield batch_i, X.take(j), y.take(j)\n",
    "\n",
    "# Initialize model parameters.\n",
    "def init_params():\n",
    "    w = nd.random_normal(scale=1, shape=(num_inputs, 1))\n",
    "    b = nd.zeros(shape=(1,))\n",
    "    params = [w, b]\n",
    "    sqrs = []\n",
    "    deltas = []\n",
    "    for param in params:\n",
    "        param.attach_grad()\n",
    "        # \n",
    "        sqrs.append(param.zeros_like())\n",
    "        deltas.append(param.zeros_like())\n",
    "    return params, sqrs, deltas\n",
    "\n",
    "# Linear regression.\n",
    "def net(X, w, b):\n",
    "    return nd.dot(X, w) + b\n",
    "\n",
    "# Loss function.\n",
    "def square_loss(yhat, y):\n",
    "    return (yhat - y.reshape(yhat.shape)) ** 2 / 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2017-10-22T11:50:58.882889Z",
     "start_time": "2017-10-22T11:50:58.555699Z"
    }
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib as mpl\n",
    "mpl.rcParams['figure.dpi']= 120\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "def train(batch_size, rho, epochs, period):\n",
    "    assert period >= batch_size and period % batch_size == 0\n",
    "    [w, b], sqrs, deltas = init_params()\n",
    "    total_loss = [np.mean(square_loss(net(X, w, b), y).asnumpy())]\n",
    "\n",
    "    # Epoch starts from 1.\n",
    "    for epoch in range(1, epochs + 1):\n",
    "        for batch_i, data, label in data_iter(batch_size):\n",
    "            with autograd.record():\n",
    "                output = net(data, w, b)\n",
    "                loss = square_loss(output, label)\n",
    "            loss.backward()\n",
    "            adadelta([w, b], sqrs, deltas, rho, batch_size)\n",
    "            if batch_i * batch_size % period == 0:\n",
    "                total_loss.append(np.mean(square_loss(net(X, w, b), y).asnumpy()))\n",
    "        print(\"Batch size %d, Epoch %d, loss %.4e\" % \n",
    "              (batch_size, epoch, total_loss[-1]))\n",
    "    print('w:', np.reshape(w.asnumpy(), (1, -1)), \n",
    "          'b:', b.asnumpy()[0], '\\n')\n",
    "    x_axis = np.linspace(0, epochs, len(total_loss), endpoint=True)\n",
    "    plt.semilogy(x_axis, total_loss)\n",
    "    plt.xlabel('epoch')\n",
    "    plt.ylabel('loss')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2017-10-22T11:51:00.431479Z",
     "start_time": "2017-10-22T11:50:58.887423Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Batch size 10, Epoch 1, loss 5.2081e-05\n",
      "Batch size 10, Epoch 2, loss 4.9538e-05\n",
      "Batch size 10, Epoch 3, loss 4.9217e-05\n",
      "w: [[ 1.99959445 -3.3999126 ]] b: 4.19964 \n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x114060b70>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "train(batch_size=10, rho=0.9999, epochs=3, period=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Next\n",
    "[AdaDalta with Gluon](../chapter06_optimization/adadelta-gluon.ipynb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For whinges or inquiries, [open an issue on  GitHub.](https://github.com/zackchase/mxnet-the-straight-dope)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
